package client.ui.view.panel.main;

import client.UserState;
import client.assets.Icons;
import client.control.Controller;
import client.control.ResponseEntity;
import client.entity.Message;
import client.entity.User;
import client.ui.component.button.MaterialButton;
import client.ui.component.divider.Divider;
import client.ui.component.edittext.InputArea;
import client.ui.component.edittext.TextEdit;
import client.ui.component.layout.VFlowLayout;
import client.ui.component.navigation.NavigationBarGroup;
import client.ui.component.navigation.NavigationBarItem;
import client.ui.component.scroll.EmptyScrollBarUI;
import client.ui.component.scroll.SmallMouseWheelListener;
import client.ui.theme.ThisFont;
import client.ui.util.MaterialColors;
import client.ui.view.base.FrameBase;
import client.ui.view.base.PanelControl;
import client.ui.view.module.ChatRecord;
import client.ui.view.module.TalkListItem;
import com.alibaba.fastjson.JSONObject;
import util.CacheUtil;

import javax.swing.*;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
  * @Description 聊天面板
  * @author 孔明浩
  * @Date 2020/3/31
  */
public class ChatPanel extends JPanel implements PanelControl,ActionListener {
    private NavigationBarGroup navigationBarGroup = new NavigationBarGroup();
    private Executor singleThreadExecutor = Executors.newFixedThreadPool(5);
    private final Map<Integer, String> names = new LinkedHashMap<>();
    private final List<Message> messages = new ArrayList<>();
    private JPanel chatRecordPanel = new JPanel(new VFlowLayout());
    private JPanel searchUserPanel = new JPanel();
    private JPanel talkListPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    private JPanel titlePanel = new JPanel();
    private JPanel contentPanel = new JPanel();
    private JPanel editPanel = new JPanel();
    private JPanel friendListPanel = new JPanel();
    private JScrollPane chatScrollPanel;
    private JLabel nameLabel = new JLabel();
    private InputArea inputArea;
    private String otherName = UserState.getUsername();
    private int otherId;
    private int userId;
    public ChatPanel(){
        super();
        initial();
        initData();
        PanelControl.panels.put("ChatPanel",this);
    }

    private void initial(){
        GridBagLayout gridBagLayout = new GridBagLayout();
        this.setLayout(gridBagLayout);
        GridBagConstraints gridBagConstraints;

        //添加搜索栏
        initSearchPanel();
        this.add(searchUserPanel);
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.anchor = GridBagConstraints.WEST;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.weightx = 0.2;
        gridBagLayout.addLayoutComponent(searchUserPanel,gridBagConstraints);

        //添加联系人栏
        //初始化联系人栏
        initTalkListPanel();
        this.add(talkListPanel);
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.anchor = GridBagConstraints.WEST;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.2;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridheight = 2;
        gridBagLayout.addLayoutComponent(talkListPanel,gridBagConstraints);

        //初始化标题栏
        initTitlePanel();
        this.add(titlePanel);
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.anchor = GridBagConstraints.CENTER;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.8;
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagLayout.addLayoutComponent(titlePanel,gridBagConstraints);

        //初始化聊天对话框
        initContentPanel();
        this.add(contentPanel);
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.anchor = GridBagConstraints.CENTER;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.8;
        gridBagConstraints.weighty = 0.8;
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagLayout.addLayoutComponent(contentPanel,gridBagConstraints);

        //初始化编辑栏
        initEditPanel();
        this.add(editPanel);
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.anchor = GridBagConstraints.CENTER;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.8;
        gridBagConstraints.weighty = 0.2;
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagLayout.addLayoutComponent(editPanel,gridBagConstraints);
    }

    private void initData(){
        //尝试初始化userId,并进行注册
        singleThreadExecutor.execute(new Runnable() {
            @Override
            public void run() {
                //根据本地数据更新联系人队列
                if (UserState.getId() != null){
                    getChatIds();
                }
                if (UserState.getUser() != null && UserState.getUser().getUserId() != null){
                    userId = UserState.getUser().getUserId();
                    names.put(UserState.getUser().getUserId(), UserState.getUsername());
                    otherId = userId;
                    Controller.CHAT_CONTROL.register(userId);
                    getChatIds();
                }
//                while (true){
//                    if (UserState.getUser() != null && UserState.getUser().getUserId() != null){
//                        userId = UserState.getUser().getUserId();
//                        names.put(UserState.getUser().getUserId(), UserState.getUsername());
//                        otherId = userId;
//                        Controller.CHAT_CONTROL.register(userId);
//                        getChatIds();
//                        break;
//                    } else {
//                        try {
//                            Thread.sleep(100);
//                        } catch (InterruptedException e) {
//                            e.printStackTrace();
//                        }
//                    }
//                }
            }
        });
        //定时更新消息队列
        Timer timer = new Timer(400, this);
        timer.setActionCommand("getData");
        timer.start();
    }

    /**
      * @Description 根据本地数据填充聊天记录
      * @author 孔明浩
      * @Date 2020/4/14
      */
    private void getChatIds() {
        for (int id: CacheUtil.readOtherId(userId)) {
            ResponseEntity responseEntity = Controller.USER_CONTROL.getOtherUserInfo(id);
            if (responseEntity.getCode() == 0){
                String name = JSONObject.parseObject(responseEntity.getData(), User.class).getUserName();
                names.put(id, name);
            }
        }
        updatePanel("");
    }

    //初始化搜索面板
    void initSearchPanel(){
        TextEdit search = new TextEdit("搜索记录");
        search.setColumn(16);
        search.setEndImage(Icons.search);
        search.getEndLabel().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                search.setEndImage(Icons.search);
                System.out.println("搜索聊天记录:" + search.getText());
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                search.setEndImage(Icons.search1);
            }

            @Override
            public void mouseExited(MouseEvent e) {
                search.setEndImage(Icons.search);
            }
        });
        searchUserPanel.add(search);
        searchUserPanel.setBorder(new EmptyBorder(8,16,0,16));
        search.setBackground(MaterialColors.BLUE_50);
        searchUserPanel.setBackground(MaterialColors.BLUE_50);
    }

    //初始化聊天列表
    void initTalkListPanel(){
        talkListPanel.setLayout(new BorderLayout());
        talkListPanel.setBorder(null);
        //滚动面板内包裹的内容版
        VFlowLayout vFlowLayout = new VFlowLayout();
        vFlowLayout.setHgap(0);
        vFlowLayout.setVgap(0);
        friendListPanel.setLayout(vFlowLayout);

        JScrollPane chatScrollPanel = new JScrollPane(friendListPanel);
        JScrollBar scrollBar = chatScrollPanel.getVerticalScrollBar();
        scrollBar.setUI(new EmptyScrollBarUI());
        scrollBar.setOpaque(true);
        chatScrollPanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        chatScrollPanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        //更改滚轮监听
        chatScrollPanel.addMouseWheelListener(new SmallMouseWheelListener(25,scrollBar));
        this.talkListPanel.add(chatScrollPanel);
    }

    //聊天界面的标题
    void initTitlePanel(){
        titlePanel.setLayout(new BorderLayout());
        titlePanel.setBackground(MaterialColors.GRAY_300);
        nameLabel = new JLabel(otherName,SwingUtilities.LEFT);
        nameLabel.setBorder(new EmptyBorder(0,36,0,24));
        nameLabel.setFont(ThisFont.BIG_BOLD_FONT);
        titlePanel.add(nameLabel,BorderLayout.WEST);
    }

    //聊天界面的内容
    void initContentPanel(){
        BorderLayout borderLayout = new BorderLayout();
        contentPanel.setLayout(borderLayout);

        chatScrollPanel = new JScrollPane(chatRecordPanel);
        chatScrollPanel.setBorder(null);
        chatScrollPanel.addMouseWheelListener(new SmallMouseWheelListener(20, chatScrollPanel.getVerticalScrollBar()));
        chatScrollPanel.getVerticalScrollBar().setValue(chatScrollPanel.getVerticalScrollBar().getMaximum());
        this.contentPanel.add(chatScrollPanel, BorderLayout.CENTER);

        JLabel divider = new Divider();
        this.contentPanel.add(divider, BorderLayout.SOUTH);
    }

    //编辑发送面板
    void initEditPanel(){
        editPanel.setLayout(new BorderLayout());
        editPanel.setBackground(MaterialColors.WHITE);
        MaterialButton sendButton = MaterialButton.BlueButton("发送",null);
        sendButton.addActionListener(this);
        sendButton.setActionCommand("sendMessage");
        inputArea = new InputArea(null,sendButton,null);
        inputArea.setInputAreaFont(ThisFont.MIDDLE_FONT);
        Box box = Box.createVerticalBox();
        JLabel label = new JLabel("编辑信息", SwingConstants.LEFT);
        label.setBackground(MaterialColors.WHITE);
        label.setForeground(MaterialColors.COSMO_BLUE);
        label.setFont(ThisFont.BIG_FONT);
        label.setOpaque(true);
        box.add(label);
        box.add(inputArea);
        editPanel.add(box);
    }

    @Override
    public void updatePanel(Object object) {
        if (object instanceof String){
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    if (object.equals("chatRecordPanel")){
                        //更新聊天内容界面
                        chatRecordPanel.removeAll();
                        for (Message m: messages) {
                            if (m == null){
                                continue;
                            }
                            ChatRecord record;
                            if (m.getSender() == UserState.getId()){
                                record = new ChatRecord(true, m, UserState.getUsername());
                            } else {
                                record = new ChatRecord(false, m, "other");
                            }
                            chatRecordPanel.add(record);
                            chatScrollPanel.getVerticalScrollBar().setValue(
                                    chatScrollPanel.getVerticalScrollBar().getMaximum());
                        }
                        chatRecordPanel.validate();
                        chatRecordPanel.repaint();

                    } else if (object.equals("friendListPanel")){
                        //更新联系人界面
                        friendListPanel.removeAll();
                        for (Map.Entry<Integer, String> m: names.entrySet()){
                            TalkListItem talkListItem = new TalkListItem(m.getValue(),null,navigationBarGroup);
                            talkListItem.addActionListener(ChatPanel.this);
                            talkListItem.setActionCommand("talkTo" + m.getKey());
                            friendListPanel.add(talkListItem);
                            JPopupMenu popupMenu = new JPopupMenu();
                            JMenuItem deleteFriend = new JMenuItem("删除");
                            deleteFriend.setActionCommand("deleteFriend" + m.getKey());
                            deleteFriend.addActionListener(ChatPanel.this);
                            popupMenu.add(deleteFriend);
                            talkListItem.setComponentPopupMenu(popupMenu);
                        }
                        friendListPanel.validate();
                        //防止重影
                        friendListPanel.repaint();
                    } else if (object.equals("")){
                        updatePanel("friendListPanel");
                        updatePanel("chatRecordPanel");
                    }
                }
            });
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (!e.getActionCommand().equals("getData")){
            System.out.println(e.getActionCommand());
        }
        switch (e.getActionCommand()){
            case "sendMessage":
                Message message = new Message();
                message.setTime(new Date());
                message.setText(inputArea.getText());
                message.setSender(userId);
                message.setReceiver(otherId);
                inputArea.setText("");
                singleThreadExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        Controller.CHAT_CONTROL.send(message);
                    }
                });
                break;
            case "getData":
                List<Message> messageList = Controller.CHAT_CONTROL.getMessages();
                //装填获取的非空message
                if (messageList.size() > 0){
                    for (Message msg: messageList) {
                        if (msg != null){
                            //启用线程查询更新发送消息的人的用户名，并更新List
                            singleThreadExecutor.execute(new Runnable() {
                                @Override
                                public void run() {
                                    ResponseEntity responseEntity = Controller.USER_CONTROL.getOtherUserInfo(msg.getSender());
                                    if (responseEntity.getCode() == 0){
                                        String name = JSONObject.parseObject(responseEntity.getData(), User.class).getUserName();
                                        names.put(msg.getSender(), name);
                                    }
                                }
                            });
                            messages.add(msg);
                        }
                    }
                    updatePanel("");
                }
                break;
            default:
                if ("talkTo".equals(e.getActionCommand().substring(0,6))){
                    otherId = Integer.parseInt(e.getActionCommand().substring(6));
                    messages.clear();
                    messages.addAll(CacheUtil.getMessagesOfOther(userId,otherId));
                    otherName = names.get(otherId);
                    nameLabel.setText(otherName);
                    updatePanel("chatRecordPanel");
                } else if ("deleteFriend".equals(e.getActionCommand().substring(0,12))){
                    int o = Integer.parseInt(e.getActionCommand().substring(12));
                    CacheUtil.deleteOtherId(userId,o);
                    names.remove(o);
                    updatePanel("");
                }
        }
    }

    /**
      * @Description 留有buyPanel调用，更改选中联系人
      * @param otherId 选中的人的Id
      * @param otherName 选中的人的姓名
      * @author 孔明浩
      * @Date 2020/4/13
      */
    public void selectItem(int otherId, String otherName){
        this.otherId = otherId;
        this.otherName = otherName;
        this.nameLabel.setText(otherName);
        if (!names.containsKey(otherId)){
            names.put(otherId, otherName);
        }
        CacheUtil.writeOtherId(userId, otherId);
        actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "talkTo" + otherId));
        updatePanel("");
    }
}
